package com.gitee.wsl.time.calendar

import com.gitee.wsl.time.atEndOfDay
import com.gitee.wsl.time.atTime
import com.gitee.wsl.time.timestamp
import com.gitee.wsl.time.toLocalDateTime
import kotlinx.datetime.LocalTime


/**
 * This implementation of the Calendar excludes (or includes - see below) a specified time range each day. For example,
 * you could use this calendar to exclude business hours (8AM - 5PM) every day. Each <CODE>DailyCalendar</CODE> only
 * allows a single time range to be specified, and that time range may not cross daily boundaries (i.e. you cannot
 * specify a time range from 8PM - 5AM). If the property <CODE>invertTimeRange</CODE> is <CODE>false</CODE> (default),
 * the time range defines a range of times in which triggers are not allowed to fire. If <CODE>invertTimeRange</CODE> is
 * <CODE>true</CODE>, the time range is inverted  that is, all times <I>outside</I> the defined time range are
 * excluded.
 *
 *
 * Note when using <CODE>DailyCalendar</CODE>, it behaves on the same principals as, for example, [ WeeklyCalendar][WeeklyCalendar]. <CODE>WeeklyCalendar</CODE> defines a set of days that are excluded <I>every week</I>. Likewise,
 * <CODE>DailyCalendar</CODE> defines a set of times that are excluded <I>every day</I>.
 *
 * @author Mike Funk, Aaron Craven
 */
class DailyCalendar(baseCalendar: Calendar?=null,
                    val rangeTime:ClosedRange<LocalTime>,
                    var invertTimeRange: Boolean = false
                    /*rangeStartingTime: LocalTime,
                    rangeEndingTime: LocalTime*/
) : AbstractCalendar(baseCalendar) {
//    private var rangeStartingHourOfDay = 0
//    private var rangeStartingMinute = 0
//    private var rangeStartingSecond = 0
//    private var rangeStartingMillis = 0
//    private var rangeEndingHourOfDay = 0
//    private var rangeEndingMinute = 0
//    private var rangeEndingSecond = 0
//    private var rangeEndingMillis = 0

    /**
     * Indicates whether the time range represents an inverted time range (see class description).
     *
     * @return a boolean indicating whether the time range is inverted
     */
    /**
     * Indicates whether the time range represents an inverted time range (see class description).
     *
     * @param flag the new value for the <CODE>invertTimeRange</CODE> flag.
     */
    //var invertTimeRange: Boolean = false

    /**
     * Create a <CODE>DailyCalendar</CODE> with a time range defined by the specified strings and no
     * <CODE>baseCalendar</CODE>. <CODE>rangeStartingTime</CODE> and <CODE>rangeEndingTime</CODE> must be in the format
     * &quot;HH:MM[:SS[:mmm]]&quot; where:
     * <UL>
     * <LI>HH is the hour of the specified time. The hour should be specified using military (24-hour) time and must be
     * in the range 0 to 23.</LI>
     * <LI>MM is the minute of the specified time and must be in the range 0 to 59.</LI>
     * <LI>SS is the second of the specified time and must be in the range 0 to 59.</LI>
     * <LI>mmm is the millisecond of the specified time and must be in the range 0 to 999.</LI>
     * <LI>items enclosed in brackets ('[', ']') are optional.</LI>
     * <LI>The time range starting time must be before the time range ending time. Note this means that a time range may
     * not cross daily boundaries (10PM - 2AM)</LI>
    </UL> *
     *
     *
     *
     * **Note:** This <CODE>DailyCalendar</CODE> will use the `[TimeZone.getDefault]` time zone
     * unless an explicit time zone is set via `[BaseCalendar.setTimeZone]`
     *
     *
     * @param rangeStartingTime a String representing the starting time for the time range
     * @param rangeEndingTime   a String representing the ending time for the the time range
     */
//    constructor(rangeStartingTime: String?, rangeEndingTime: String?) : super() {
//        setTimeRange(rangeStartingTime, rangeEndingTime)
//    }

    /**
     * Create a <CODE>DailyCalendar</CODE> with a time range defined by the specified strings and the specified
     * <CODE>baseCalendar</CODE>. <CODE>rangeStartingTime</CODE> and <CODE>rangeEndingTime</CODE> must be in the format
     * &quot;HH:MM[:SS[:mmm]]&quot; where:
     * <UL>
     * <LI>HH is the hour of the specified time. The hour should be specified using military (24-hour) time and must be
     * in the range 0 to 23.</LI>
     * <LI>MM is the minute of the specified time and must be in the range 0 to 59.</LI>
     * <LI>SS is the second of the specified time and must be in the range 0 to 59.</LI>
     * <LI>mmm is the millisecond of the specified time and must be in the range 0 to 999.</LI>
     * <LI>items enclosed in brackets ('[', ']') are optional.</LI>
     * <LI>The time range starting time must be before the time range ending time. Note this means that a time range may
     * not cross daily boundaries (10PM - 2AM)</LI>
    </UL> *
     *
     *
     *
     * **Note:** This <CODE>DailyCalendar</CODE> will use the `[TimeZone.getDefault]` time zone
     * unless an explicit time zone is set via `[BaseCalendar.setTimeZone]`
     *
     *
     * @param baseCalendar      the base calendar for this calendar instance  see [BaseCalendar] for more information on
     * base calendar functionality
     * @param rangeStartingTime a String representing the starting time for the time range
     * @param rangeEndingTime   a String representing the ending time for the time range
     */
//    constructor(
//        baseCalendar: ICalendar?,
//        rangeStartingTime: String?,
//        rangeEndingTime: String?,
//    ) : super(baseCalendar) {
//        setTimeRange(rangeStartingTime, rangeEndingTime)
//    }
//
//    constructor(
//        baseCalendar: ICalendar?,
//        rangeStartingTime: java.time.LocalTime?,
//        rangeEndingTime: java.time.LocalTime?,
//    ) : super(baseCalendar) {
//        setTimeRange(rangeStartingTime, rangeEndingTime)
//    }

    /**
     * Create a <CODE>DailyCalendar</CODE> with a time range defined by the specified values and no
     * <CODE>baseCalendar</CODE>. Values are subject to the following validations:
     * <UL>
     * <LI>Hours must be in the range 0-23 and are expressed using military (24-hour) time.</LI>
     * <LI>Minutes must be in the range 0-59</LI>
     * <LI>Seconds must be in the range 0-59</LI>
     * <LI>Milliseconds must be in the range 0-999</LI>
     * <LI>The time range starting time must be before the time range ending time. Note this means that a time range may
     * not cross daily boundaries (10PM - 2AM)</LI>
    </UL> *
     *
     *
     *
     * **Note:** This <CODE>DailyCalendar</CODE> will use the `[TimeZone.getDefault]` time zone
     * unless an explicit time zone is set via `[BaseCalendar.setTimeZone]`
     *
     *
     * @param rangeStartingHourOfDay the hour of the start of the time range
     * @param rangeStartingMinute    the minute of the start of the time range
     * @param rangeStartingSecond    the second of the start of the time range
     * @param rangeStartingMillis    the millisecond of the start of the time range
     * @param rangeEndingHourOfDay   the hour of the end of the time range
     * @param rangeEndingMinute      the minute of the end of the time range
     * @param rangeEndingSecond      the second of the end of the time range
     * @param rangeEndingMillis      the millisecond of the start of the time range
     */
//    constructor(
//        rangeStartingHourOfDay: Int,
//        rangeStartingMinute: Int,
//        rangeStartingSecond: Int,
//        rangeStartingMillis: Int,
//        rangeEndingHourOfDay: Int,
//        rangeEndingMinute: Int,
//        rangeEndingSecond: Int,
//        rangeEndingMillis: Int,
//        baseCalendar: Calendar?=null,
//    ) : this(baseCalendar) {
//        setTimeRange(
//            rangeStartingHourOfDay, rangeStartingMinute, rangeStartingSecond, rangeStartingMillis,
//            rangeEndingHourOfDay, rangeEndingMinute, rangeEndingSecond, rangeEndingMillis
//        )
//    }

    /**
     * Create a <CODE>DailyCalendar</CODE> with a time range defined by the specified values and the specified
     * <CODE>baseCalendar</CODE>. Values are subject to the following validations:
     * <UL>
     * <LI>Hours must be in the range 0-23 and are expressed using military (24-hour) time.</LI>
     * <LI>Minutes must be in the range 0-59</LI>
     * <LI>Seconds must be in the range 0-59</LI>
     * <LI>Milliseconds must be in the range 0-999</LI>
     * <LI>The time range starting time must be before the time range ending time. Note this means that a time range may
     * not cross daily boundaries (10PM - 2AM)</LI>
    </UL> *
     *
     *
     *
     * **Note:** This <CODE>DailyCalendar</CODE> will use the `[TimeZone.getDefault]` time zone
     * unless an explicit time zone is set via `[BaseCalendar.setTimeZone]`
     *
     *
     * @param baseCalendar           the base calendar for this calendar instance  see [BaseCalendar] for more information on
     * base calendar functionality
     * @param rangeStartingHourOfDay the hour of the start of the time range
     * @param rangeStartingMinute    the minute of the start of the time range
     * @param rangeStartingSecond    the second of the start of the time range
     * @param rangeStartingMillis    the millisecond of the start of the time range
     * @param rangeEndingHourOfDay   the hour of the end of the time range
     * @param rangeEndingMinute      the minute of the end of the time range
     * @param rangeEndingSecond      the second of the end of the time range
     * @param rangeEndingMillis      the millisecond of the start of the time range
     */
//    constructor(
//        baseCalendar: ICalendar?,
//        rangeStartingHourOfDay: Int,
//        rangeStartingMinute: Int,
//        rangeStartingSecond: Int,
//        rangeStartingMillis: Int,
//        rangeEndingHourOfDay: Int,
//        rangeEndingMinute: Int,
//        rangeEndingSecond: Int,
//        rangeEndingMillis: Int,
//    ) : super(baseCalendar) {
//        setTimeRange(
//            rangeStartingHourOfDay, rangeStartingMinute, rangeStartingSecond, rangeStartingMillis,
//            rangeEndingHourOfDay, rangeEndingMinute, rangeEndingSecond, rangeEndingMillis
//        )
//    }

    /**
     * Determines whether the given time (in milliseconds) is 'included' by the <CODE>BaseCalendar</CODE>
     *
     * @param timeStamp the date/time to test
     * @return a boolean indicating whether the specified time is 'included' by the <CODE>BaseCalendar</CODE>
     */
    override fun isTimeIncluded(timeStamp: Long): Boolean {
        if (timeStamp <= 0) return false

        if (baseCalendar != null && !baseCalendar!!.isTimeIncluded(timeStamp)) {
            return false
        }

        /*
        val startOfDayInMillis: Long = getStartOfDayJavaCalendar(timeInMillis).getTime().getTime()
        val endOfDayInMillis: Long = getEndOfDayJavaCalendar(timeInMillis).getTime().getTime()
        val timeRangeStartingTimeInMillis = getTimeRangeStartingTimeInMillis(timeInMillis)
        val timeRangeEndingTimeInMillis = getTimeRangeEndingTimeInMillis(timeInMillis)
        return if (!invertTimeRange) {
            ((timeInMillis in (startOfDayInMillis + 1)..<timeRangeStartingTimeInMillis)
                    || (timeInMillis in (timeRangeEndingTimeInMillis + 1)..<endOfDayInMillis))
        } else {
            ((timeInMillis >= timeRangeStartingTimeInMillis) && (timeInMillis <= timeRangeEndingTimeInMillis))
        }
        */

        val dateTime = timeStamp.toLocalDateTime().time
        val inTime = dateTime in rangeTime
        return if (!invertTimeRange) inTime else !inTime
    }

    /**
     * Determines the next time included by the <CODE>DailyCalendar</CODE> after the specified time.
     *
     * @param timeStamp the initial date/time after which to find an included time
     * @return the time in milliseconds representing the next time included after the specified time.
     */
    override fun getNextIncludedTime(timeStamp: Long): Long {
        var nextIncludedTime = timeStamp + oneMillis
        var nextTime:LocalTime
        while (!isTimeIncluded(nextIncludedTime)) {
            nextTime = nextIncludedTime.toLocalDateTime().time
            if (!invertTimeRange) {
              if(nextTime in rangeTime)
                  nextIncludedTime = getTimeRangeEndingTimeInMillis(nextIncludedTime) + oneMillis
              else if ((baseCalendar != null) && (!baseCalendar!!.isTimeIncluded(nextIncludedTime))) {
                    nextIncludedTime = baseCalendar!!.getNextIncludedTime(nextIncludedTime)
                } else {
                    nextIncludedTime++
                }
            } else {
                // If the time is in a range excluded by this calendar, we can
                // move to the end of the excluded time range and continue
                // testing from there. Otherwise, if nextIncludedTime is
                // excluded by the baseCalendar, ask it the next time it
                // includes and begin testing from there. Failing this, add one
                // millisecond and continue testing.
                if (nextTime < rangeTime.start) {
                    nextIncludedTime = getTimeRangeStartingTimeInMillis(nextIncludedTime)
                } else if (nextTime > rangeTime.endInclusive) {
                    // (move to start of next day)
                    nextIncludedTime = nextIncludedTime.toLocalDateTime().atEndOfDay.timestamp
                    nextIncludedTime += 1L
                } else if ((baseCalendar != null) && (!baseCalendar!!.isTimeIncluded(nextIncludedTime))) {
                    nextIncludedTime = baseCalendar!!.getNextIncludedTime(nextIncludedTime)
                } else {
                    nextIncludedTime++
                }
            }
        }
        return nextIncludedTime

//        while (!isTimeIncluded(nextIncludedTime)) {
//            if (!invertTimeRange) {
//                // If the time is in a range excluded by this calendar, we can
//                // move to the end of the excluded time range and continue
//                // testing from there. Otherwise, if nextIncludedTime is
//                // excluded by the baseCalendar, ask it the next time it
//                // includes and begin testing from there. Failing this, add one
//                // millisecond and continue testing.
//                if ((nextIncludedTime >= getTimeRangeStartingTimeInMillis(nextIncludedTime))
//                    && (nextIncludedTime <= getTimeRangeEndingTimeInMillis(nextIncludedTime))
//                ) {
//                    nextIncludedTime = getTimeRangeEndingTimeInMillis(nextIncludedTime) + oneMillis
//                } else if ((baseCalendar != null) && (!baseCalendar!!.isTimeIncluded(
//                        nextIncludedTime
//                    ))
//                ) {
//                    nextIncludedTime = baseCalendar!!.getNextIncludedTime(nextIncludedTime)
//                } else {
//                    nextIncludedTime++
//                }
//            } else {
//                // If the time is in a range excluded by this calendar, we can
//                // move to the end of the excluded time range and continue
//                // testing from there. Otherwise, if nextIncludedTime is
//                // excluded by the baseCalendar, ask it the next time it
//                // includes and begin testing from there. Failing this, add one
//                // millisecond and continue testing.
//                if (nextIncludedTime < getTimeRangeStartingTimeInMillis(nextIncludedTime)) {
//                    nextIncludedTime = getTimeRangeStartingTimeInMillis(nextIncludedTime)
//                } else if (nextIncludedTime > getTimeRangeEndingTimeInMillis(nextIncludedTime)) {
//                    // (move to start of next day)
//                    nextIncludedTime = getEndOfDayJavaCalendar(nextIncludedTime).getTime().getTime()
//                    nextIncludedTime += 1L
//                } else if ((baseCalendar != null) && (!baseCalendar!!.isTimeIncluded(
//                        nextIncludedTime
//                    ))
//                ) {
//                    nextIncludedTime = baseCalendar!!.getNextIncludedTime(nextIncludedTime)
//                } else {
//                    nextIncludedTime++
//                }
//            }
//        }
//
//        return nextIncludedTime
    }



    /**
     * Returns the start time of the time range (in milliseconds) of the day specified in <CODE>timeInMillis</CODE>
     *
     * @param timeInMillis a time containing the desired date for the starting time of the time range.
     * @return a date/time (in milliseconds) representing the start time of the time range for the specified date.
     */
    fun getTimeRangeStartingTimeInMillis(timeInMillis: Long): Long {
        return timeInMillis.toLocalDateTime().atTime(rangeTime.start).timestamp
    }

    fun getTimeRangeEndingTimeInMillis(timeInMillis: Long): Long {
        return timeInMillis.toLocalDateTime().atTime(rangeTime.endInclusive).timestamp
    }


//    fun getTimeRangeStartingTimeInMillis(timeInMillis: Long): Long {
//        val rangeStartingTime: Calendar = createJavaCalendar(timeInMillis)
//        rangeStartingTime.set(Calendar.HOUR_OF_DAY, rangeStartingHourOfDay)
//        rangeStartingTime.set(Calendar.MINUTE, rangeStartingMinute)
//        rangeStartingTime.set(Calendar.SECOND, rangeStartingSecond)
//        rangeStartingTime.set(Calendar.MILLISECOND, rangeStartingMillis)
//        return rangeStartingTime.getTime().getTime()
//    }

    /**
     * Returns the end time of the time range (in milliseconds) of the day specified in <CODE>timeInMillis</CODE>
     *
     * @param timeInMillis a time containing the desired date for the ending time of the time range.
     * @return a date/time (in milliseconds) representing the end time of the time range for the specified date.
     */
//    fun getTimeRangeEndingTimeInMillis(timeInMillis: Long): Long {
//        val rangeEndingTime: Calendar = createJavaCalendar(timeInMillis)
//        rangeEndingTime.set(Calendar.HOUR_OF_DAY, rangeEndingHourOfDay)
//        rangeEndingTime.set(Calendar.MINUTE, rangeEndingMinute)
//        rangeEndingTime.set(Calendar.SECOND, rangeEndingSecond)
//        rangeEndingTime.set(Calendar.MILLISECOND, rangeEndingMillis)
//        return rangeEndingTime.getTime().getTime()
//    }

    /**
     * Returns a string representing the properties of the <CODE>DailyCalendar</CODE>
     *
     * @return the properteis of the DailyCalendar in a String format
     */
//    override fun toString(): String {
//        val numberFormatter: java.text.NumberFormat = java.text.NumberFormat.getNumberInstance()
//        numberFormatter.setMaximumFractionDigits(0)
//        numberFormatter.setMinimumIntegerDigits(2)
//        val buffer: java.lang.StringBuffer = java.lang.StringBuffer()
//        buffer.append("base calendar: [")
//        if (getBaseCalendar() != null) {
//            buffer.append(getBaseCalendar().toString())
//        } else {
//            buffer.append("null")
//        }
//        buffer.append("], time range: '")
//        buffer.append(numberFormatter.format(rangeStartingHourOfDay.toLong()))
//        buffer.append(":")
//        buffer.append(numberFormatter.format(rangeStartingMinute.toLong()))
//        buffer.append(":")
//        buffer.append(numberFormatter.format(rangeStartingSecond.toLong()))
//        buffer.append(":")
//        numberFormatter.setMinimumIntegerDigits(3)
//        buffer.append(numberFormatter.format(rangeStartingMillis.toLong()))
//        numberFormatter.setMinimumIntegerDigits(2)
//        buffer.append(" - ")
//        buffer.append(numberFormatter.format(rangeEndingHourOfDay.toLong()))
//        buffer.append(":")
//        buffer.append(numberFormatter.format(rangeEndingMinute.toLong()))
//        buffer.append(":")
//        buffer.append(numberFormatter.format(rangeEndingSecond.toLong()))
//        buffer.append(":")
//        numberFormatter.setMinimumIntegerDigits(3)
//        buffer.append(numberFormatter.format(rangeEndingMillis.toLong()))
//        buffer.append("', inverted: $invertTimeRange]")
//        return buffer.toString()
//    }

    /**
     * Helper method to split the given string by the given delimiter.
     */
//    private fun split(string: String, delim: String): Array<String> {
//        val result: java.util.ArrayList<String> = java.util.ArrayList<String>()
//
//        val stringTokenizer: java.util.StringTokenizer = java.util.StringTokenizer(string, delim)
//        while (stringTokenizer.hasMoreTokens()) {
//            result.add(stringTokenizer.nextToken())
//        }
//
//        return result.toTypedArray<String>()
//    }

    /**
     * Sets the time range for the <CODE>DailyCalendar</CODE> to the times represented in the specified Strings.
     *
     * @param rangeStartingTimeString a String representing the start time of the time range
     * @param rangeEndingTimeString   a String representing the end time of the excluded time range
     */
//    fun setTimeRange(rangeStartingTimeString: String, rangeEndingTimeString: String) {
//        val rStartingHourOfDay: Int
//        val rStartingMinute: Int
//        val rStartingSecond: Int
//        val rStartingMillis: Int
//        val rEndingHourOfDay: Int
//        val rEndingMinute: Int
//        val rEndingSecond: Int
//        val rEndingMillis: Int
//
//        val rangeStartingTime: Array<String>=split(rangeStartingTimeString, DailyCalendar.Companion.colon)
//
//        require(!((rangeStartingTime.size < 2) || (rangeStartingTime.size > 4))) { "Invalid time string '$rangeStartingTimeString'" }
//
//        rStartingHourOfDay = rangeStartingTime[0].toInt()
//        rStartingMinute = rangeStartingTime[1].toInt()
//        rStartingSecond = if (rangeStartingTime.size > 2) {
//            rangeStartingTime[2].toInt()
//        } else {
//            0
//        }
//        rStartingMillis = if (rangeStartingTime.size == 4) {
//            rangeStartingTime[3].toInt()
//        } else {
//            0
//        }
//
//        val rEndingTime: Array<String>=split(rangeEndingTimeString, DailyCalendar.Companion.colon)
//
//        require(!((rEndingTime.size < 2) || (rEndingTime.size > 4))) { "Invalid time string '$rangeEndingTimeString'" }
//
//        rEndingHourOfDay = rEndingTime[0].toInt()
//        rEndingMinute = rEndingTime[1].toInt()
//        rEndingSecond = if (rEndingTime.size > 2) {
//            rEndingTime[2].toInt()
//        } else {
//            0
//        }
//        rEndingMillis = if (rEndingTime.size == 4) {
//            rEndingTime[3].toInt()
//        } else {
//            0
//        }
//
//        setTimeRange(
//            rStartingHourOfDay, rStartingMinute, rStartingSecond, rStartingMillis, rEndingHourOfDay,
//            rEndingMinute, rEndingSecond, rEndingMillis
//        )
//    }

    /**
     * Sets the time range for the <CODE>DailyCalendar</CODE> to the times represented in the specified values.
     *
     * @param rangeStartingHourOfDay the hour of the start of the time range
     * @param rangeStartingMinute    the minute of the start of the time range
     * @param rangeStartingSecond    the second of the start of the time range
     * @param rangeStartingMillis    the millisecond of the start of the time range
     * @param rangeEndingHourOfDay   the hour of the end of the time range
     * @param rangeEndingMinute      the minute of the end of the time range
     * @param rangeEndingSecond      the second of the end of the time range
     * @param rangeEndingMillis      the millisecond of the start of the time range
     */
//    fun setTimeRange(
//        rangeStartingHourOfDay: Int,
//        rangeStartingMinute: Int,
//        rangeStartingSecond: Int,
//        rangeStartingMillis: Int,
//        rangeEndingHourOfDay: Int,
//        rangeEndingMinute: Int,
//        rangeEndingSecond: Int,
//        rangeEndingMillis: Int,
//    ) {
//        validate(
//            rangeStartingHourOfDay,
//            rangeStartingMinute,
//            rangeStartingSecond,
//            rangeStartingMillis
//        )
//
//        validate(rangeEndingHourOfDay, rangeEndingMinute, rangeEndingSecond, rangeEndingMillis)
//
//        val startCal: Calendar = createJavaCalendar()
//        startCal.set(Calendar.HOUR_OF_DAY, rangeStartingHourOfDay)
//        startCal.set(Calendar.MINUTE, rangeStartingMinute)
//        startCal.set(Calendar.SECOND, rangeStartingSecond)
//        startCal.set(Calendar.MILLISECOND, rangeStartingMillis)
//
//        val endCal: Calendar = createJavaCalendar()
//        endCal.set(Calendar.HOUR_OF_DAY, rangeEndingHourOfDay)
//        endCal.set(Calendar.MINUTE, rangeEndingMinute)
//        endCal.set(Calendar.SECOND, rangeEndingSecond)
//        endCal.set(Calendar.MILLISECOND, rangeEndingMillis)
//
//        require(startCal.before(endCal)) {
//            (invalidTimeRange + rangeStartingHourOfDay + ":" + rangeStartingMinute
//                    + ":" + rangeStartingSecond + ":" + rangeStartingMillis + separator + rangeEndingHourOfDay + ":"
//                    + rangeEndingMinute + ":" + rangeEndingSecond + ":" + rangeEndingMillis)
//        }
//
//        this.rangeStartingHourOfDay = rangeStartingHourOfDay
//        this.rangeStartingMinute = rangeStartingMinute
//        this.rangeStartingSecond = rangeStartingSecond
//        this.rangeStartingMillis = rangeStartingMillis
//        this.rangeEndingHourOfDay = rangeEndingHourOfDay
//        this.rangeEndingMinute = rangeEndingMinute
//        this.rangeEndingSecond = rangeEndingSecond
//        this.rangeEndingMillis = rangeEndingMillis
//    }

    /**
     * Sets the time range for the <CODE>DailyCalendar</CODE> to the times represented in the specified
     * <CODE>java.util.Calendar</CODE>s.
     *
     * @param rangeStartingCalendar a Calendar containing the start time for the <CODE>DailyCalendar</CODE>
     * @param rangeEndingCalendar   a Calendar containing the end time for the <CODE>DailyCalendar</CODE>
     */
//    fun setTimeRange(
//        rangeStartingCalendar: LocalTime,
//        rangeEndingCalendar: LocalTime,
//    ) {
//        setTimeRange(
//            rangeStartingCalendar.getHour(),
//            rangeStartingCalendar.getMinute(),
//            rangeStartingCalendar.getSecond(),
//            0,
//            rangeEndingCalendar.getHour(),
//            rangeEndingCalendar.getMinute(),
//            rangeEndingCalendar.getSecond(),
//            0
//        )
//    }

    /**
     * Checks the specified values for validity as a set of time values.
     *
     * @param hourOfDay the hour of the time to check (in military (24-hour) time)
     * @param minute    the minute of the time to check
     * @param second    the second of the time to check
     * @param millis    the millisecond of the time to check
     */
    private fun validate(hourOfDay: Int, minute: Int, second: Int, millis: Int) {
        require(!(hourOfDay < 0 || hourOfDay > 23)) { invalidHourOfDay + hourOfDay }
        require(!(minute < 0 || minute > 59)) { invalidMinute + minute }
        require(!(second < 0 || second > 59)) { invalidSecond + second }
        require(!(millis < 0 || millis > 999)) { invalidMillis + millis }
    }

    companion object {
        const val serialVersionUID: Long = -7561220099904944039L

        private const val invalidHourOfDay = "Invalid hour of day: "
        private const val invalidMinute = "Invalid minute: "
        private const val invalidSecond = "Invalid second: "
        private const val invalidMillis = "Invalid millis: "
        private const val invalidTimeRange = "Invalid time range: "
        private const val separator = " - "
        private const val oneMillis: Long = 1
        private const val colon = ":"
    }
}